<!DOCTYPE html>
<html>
<head>
<script src="../../resources/js-test.js"></script>
<style>
#drag {
    border: 1px solid black;
    height: 200px;
    width: 200px;
}
#drop {
    border: 1px solid black;
    height: 200px;
    width: 200px;
}
</style>
<script>
function legacyDragStart(dataTransfer)
{
    dataTransfer.setData('text', 'sample');
    dataTransfer.setData('url', 'http://www.google.com/');
    dataTransfer.setData('text/html', '<em>Markup</em>');
    dataTransfer.setData('custom-data', 'hello world');
}

var testDataTransfer;
var testItem;
function itemListDragStart(dataTransfer)
{
    testDataTransfer = dataTransfer;
    shouldThrow('testDataTransfer.items.add()');
    shouldThrow('testDataTransfer.items.add(undefined)');
    shouldThrow('testDataTransfer.items.add("sample")');
    shouldThrow('testDataTransfer.items.add(null)');
    testItem = dataTransfer.items.add('sample', 'text/plain');
    shouldBeEqualToString('testItem.kind', 'string');
    shouldBeEqualToString('testItem.type', 'text/plain');
    testItem = dataTransfer.items.add('http://www.google.com/', 'text/uri-list');
    shouldBeEqualToString('testItem.kind', 'string');
    shouldBeEqualToString('testItem.type', 'text/uri-list');
    testItem = dataTransfer.items.add('<em>Markup</em>', 'text/html');
    shouldBeEqualToString('testItem.kind', 'string');
    shouldBeEqualToString('testItem.type', 'text/html');
    testItem = dataTransfer.items.add('hello world', 'custom-data');
    shouldBeEqualToString('testItem.kind', 'string');
    shouldBeEqualToString('testItem.type', 'custom-data');
}

function dragstart(event)
{
    var dragMethod = document.getElementById('dragMethod');
    if (dragMethod.selectedIndex == 0)
        legacyDragStart(event.dataTransfer);
    else if (dragMethod.selectedIndex == 1)
        itemListDragStart(event.dataTransfer);
}

function dragenter(event)
{
    event.preventDefault();
}

function dragover(event)
{
    event.preventDefault();
}

function legacyDrop(dataTransfer)
{
    testDataTransfer = dataTransfer;
    shouldBe('testDataTransfer.types.length', '4');
    shouldBeTrue('testDataTransfer.types.indexOf("text/plain") >= 0');
    shouldBeTrue('testDataTransfer.types.indexOf("text/uri-list") >= 0');
    shouldBeTrue('testDataTransfer.types.indexOf("text/html") >= 0');
    shouldBeTrue('testDataTransfer.types.indexOf("custom-data") >= 0');
    shouldBeEqualToString('testDataTransfer.getData("text")', 'sample');
    shouldBeEqualToString('testDataTransfer.getData("url")', 'http://www.google.com/');
    shouldBeEqualToString('testDataTransfer.getData("text/html")', '<em>Markup</em>');
    shouldBeEqualToString('testDataTransfer.getData("custom-data")', 'hello world');
    setTimeout(runNext, 0);
}

var outstandingRequests;
var types, expectedTypes;
var testData, expectedTestData;
function itemListDrop(dataTransfer)
{
    testDataTransfer = dataTransfer;
    outstandingRequests = 0;
    shouldBe('testDataTransfer.items.length', '4');
    shouldBeNull('testDataTransfer.items.add("test", "text/plain")'); // Read-only.
    shouldBe('testDataTransfer.items.length', '4');
    types = [];
    for (var i = 0; i < dataTransfer.items.length; ++i) {
        types.push({kind: dataTransfer.items[i].kind, type: dataTransfer.items[i].type});
    }
    types.sort(function (a, b) { return a.type.localeCompare(b.type); });
    expectedTypes = [
        { kind: 'string', type: 'custom-data'},
        { kind: 'string', type: 'text/html'},
        { kind: 'string', type: 'text/plain'},
        { kind: 'string', type: 'text/uri-list'},
    ];
    shouldBe('JSON.stringify(expectedTypes)', 'JSON.stringify(types)');
    var expectedResults = {
        'custom-data': 'hello world',
        'text/html': '<em>Markup</em>',
        'text/plain': 'sample',
        'text/uri-list': 'http://www.google.com/',
    }
    function makeClosure(expectedData)
    {
        ++outstandingRequests;
        return function (data) {
            expectedTestData = expectedData;
            testData = data;
            shouldBe('testData', 'expectedTestData');
            if (--outstandingRequests == 0)
                setTimeout(runNext, 0);
        }
    }
    // We use this funky loop to make sure we always print out results in the same order.
    for (var i = 0; i < types.length; ++i) {
        for (var j = 0; j < dataTransfer.items.length; ++j) {
            if (types[i].type == dataTransfer.items[j].type) {
                dataTransfer.items[j].getAsString(makeClosure(expectedResults[types[i].type]));
                break;
            }
        }
    }
}

function drop(event)
{
    var dropMethod = document.getElementById('dropMethod');
    if (dropMethod.selectedIndex == 0)
        legacyDrop(event.dataTransfer);
    else if (dropMethod.selectedIndex == 1)
        itemListDrop(event.dataTransfer);
    event.preventDefault();
}

function runTest(dragMethodIndex, dropMethodIndex)
{
    var dragMethod = document.getElementById('dragMethod');
    var dropMethod = document.getElementById('dropMethod');
    dragMethod.selectedIndex = dragMethodIndex;
    dropMethod.selectedIndex = dropMethodIndex;
    debug('Running test with ' + dragMethod.value + ' drag handler and ' + dropMethod.value + ' drop handler');

    var dragElement = document.getElementById('drag');
    eventSender.mouseMoveTo(dragElement.offsetLeft + dragElement.offsetWidth / 2,
                            dragElement.offsetTop + dragElement.offsetHeight / 2);
    eventSender.mouseDown();
    eventSender.leapForward(100);
    var dropElement = document.getElementById('drop');
    eventSender.mouseMoveTo(dropElement.offsetLeft + dropElement.offsetWidth / 2,
                            dropElement.offsetTop + dropElement.offsetHeight / 2);
    eventSender.mouseUp();
}

var testCases = [
    [0, 0],
    [0, 1],
    [1, 0],
    [1, 1],
];
function runNext()
{
    if (!window.testRunner)
        return;
    var testCase = testCases.shift();
    if (testCase)
        runTest.apply(null, testCase);
    else
        finishJSTest();
}
</script>
</head>
<body>
<p>To manually test, drag 'Drag Me' to 'Drop Here' and drop.  Several lines that say 'PASS' should appear below.
<div draggable="true" id="drag" ondragstart="dragstart(event)">Drag Me</div>
<div id="drop" ondragenter="dragenter(event)" ondragover="dragover(event)" ondrop="drop(event)">Drop Here</div>
</div>
<div>Drag handler: <select id="dragMethod"><option>Legacy</option><option>DataTransferItemList</option></select></div>
<div>Drop handler: <select id="dropMethod"><option>Legacy</option><option>DataTransferItemList</option></select></div>
<div id="console"></div>
<script>
description("Tests drag'n drop and well as DataTransferItemList");
window.jsTestIsAsync = true;

runNext();
</script>
</body>
</html>
